home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-01 / ue312src.zip / NT.C < prev    next >
C/C++ Source or Header  |  1993-01-05  |  18KB  |  571 lines

  1. /*      NT.C:           Operating specific I/O and Spawning functions
  2.  *                      for the Window NT operating system (console mode)
  3.  *                      for MicroEMACS 3.12
  4.  *                      (C)Copyright 1993 by Daniel M. Lawrence
  5.  *                      Windows NT version by Walter Warniaha
  6.  *
  7.  * Note:  don't try to compile this on non Windows NT systems....  The header
  8.  *        files won't exist.
  9.  *
  10.  * Modifications needed: check that we don't construct command lines and
  11.  * temporary filenames which are too large for their buffers.
  12.  *
  13.  */
  14.  
  15.  
  16. #undef  PASCAL
  17. #undef  NEAR
  18. #undef  HIBYTE
  19.  
  20. #include        "estruct.h"
  21. #include        "eproto.h"
  22.  
  23. #if     WINNT
  24.  
  25. #include "elang.h"
  26. #include "edef.h"
  27. #include <process.h>
  28. #include <io.h>
  29.  
  30. /*
  31.  * Create a subjob with a copy of the command intrepreter in it. When the
  32.  * command interpreter exits, mark the screen as garbage so that you do a full
  33.  * repaint. Bound to "^X C". The message at the start in VMS puts out a newline.
  34.  * Under some (unknown) condition, you don't get one free when DCL starts up.
  35.  */
  36. PASCAL NEAR spawncli(f, n)
  37. {
  38.         /* don't allow this command if restricted */
  39.         if (restflag)
  40.                 return(resterr());
  41.  
  42.         movecursor(term.t_nrow, 0);             /* Seek to last line.   */
  43.         TTflush();
  44.         TTkclose();
  45.         shell();
  46.         TTkopen();
  47.         sgarbf = TRUE;
  48.         return(TRUE);
  49. }
  50.  
  51.  
  52. /*
  53.  * Run a one-liner in a subjob. When the command returns, wait for a single
  54.  * character to be typed, then mark the screen as garbage so a full repaint is
  55.  * done. Bound to "C-X !".
  56.  */
  57. PASCAL NEAR spawn(f, n)
  58. {
  59.         register int s;
  60.         char line[NLINE];
  61.  
  62.         /* don't allow this command if restricted */
  63.         if (restflag)
  64.                 return(resterr());
  65.  
  66.         if ((s=mlreply("!", line, NLINE)) != TRUE)
  67.                 return(s);
  68.         movecursor(term.t_nrow - 1, 0);
  69.         TTkclose();
  70.         system(line);
  71.         TTkopen();
  72.         /* if we are interactive, pause here */
  73.         if (clexec == FALSE) {
  74.                 puts(TEXT6);
  75. /*                     "\r\n\n[End]" */
  76.                 tgetc();
  77.         }
  78.         sgarbf = TRUE;
  79.         return (TRUE);
  80. }
  81.  
  82.  
  83. /*
  84.  * Run an external program with arguments. When it returns, wait for a single
  85.  * character to be typed, then mark the screen as garbage so a full repaint is
  86.  * done. Bound to "C-X $".
  87.  */
  88.  
  89. PASCAL NEAR execprg(f, n)
  90. {
  91.         register int s;
  92.         char line[NLINE];
  93.  
  94.         /* don't allow this command if restricted */
  95.         if (restflag)
  96.                 return(resterr());
  97.  
  98.         if ((s=mlreply("$", line, NLINE)) != TRUE)
  99.                 return(s);
  100.         movecursor(term.t_nrow - 1, 0);
  101.         TTkclose();
  102.         execprog(line);
  103.         TTkopen();
  104.         /* if we are interactive, pause here */
  105.         if (clexec == FALSE) {
  106.                 puts(TEXT6);
  107. /*                     "\r\n\n[End]" */
  108.                 tgetc();
  109.         }
  110.         sgarbf = TRUE;
  111.         return (TRUE);
  112. }
  113.  
  114. /*
  115.  * Pipe a one line command into a window
  116.  * Bound to ^X @
  117.  * We use a unique temporary file name so that multiple instances of
  118.  * MicroEMACS don't try to use the same file.
  119.  */
  120. PASCAL NEAR pipecmd(f, n)
  121. {
  122.         register WINDOW *wp;    /* pointer to new window */
  123.         register BUFFER *bp;    /* pointer to buffer to zot */
  124.         register char *tmp;     /* ptr to TMP DOS environment variable */
  125.         char line[NLINE];       /* command line send to shell */
  126.         static char bname[] = "command";
  127.         static char filnam[NSTRING];
  128.         char *getenv();
  129.  
  130.         /* don't allow this command if restricted */
  131.         if (restflag)
  132.                 return(resterr());
  133.  
  134.         /* get rid of the command output buffer if it exists */
  135.         if ((bp=bfind(bname, FALSE, 0)) != FALSE) {
  136.                 /* try to make sure we are off screen */
  137.                 wp = wheadp;
  138.                 while (wp != NULL) {
  139.                         if (wp->w_bufp == bp) {
  140.                                 onlywind(FALSE, 1);
  141.                                 break;
  142.                         }
  143.                         wp = wp->w_wndp;
  144.                 }
  145.                 /* get rid of the existing command buffer */
  146.                 if (zotbuf(bp) != TRUE)
  147.                         return(FALSE);
  148.         }
  149.  
  150.         /* get the command to pipe in */
  151.         if (mlreply("@", line, NLINE) != TRUE)
  152.                 return(FALSE);
  153.  
  154.         /* Call mktemp() to get a unique filename in the tmp directory. */
  155.         if ((tmp = getenv("TMP")) == NULL)
  156.                 filnam[0] = 0;
  157.         else {
  158.                 strcpy(filnam, tmp);
  159.                 if (filnam[strlen(filnam) - 1] != '\\')
  160.                         strcat(filnam, "\\");
  161.         }
  162.         strcat(filnam,"eXXXXXX");
  163.         mktemp(filnam);
  164.  
  165.         /* redirect the command output to the output file */
  166.         strcat(line, " >>");
  167.         strcat(line, filnam);
  168.         movecursor(term.t_nrow - 1, 0);
  169.  
  170.         /* execute the command */
  171.         TTkclose();
  172.         system(line);
  173.         TTkopen();
  174.         sgarbf = TRUE;
  175.  
  176.         /* did the output file get generated? */
  177.         if (access( filnam, 0) != 0)
  178.                 return(FALSE);
  179.  
  180.         /* split the current window to make room for the command output */
  181.         if (splitwind(FALSE, 1) == FALSE)
  182.                         return(FALSE);
  183.  
  184.         /* and read the stuff in */
  185.         if (getfile(filnam, FALSE) == FALSE)
  186.                 return(FALSE);
  187.  
  188.         /* rename the buffer */
  189.         strcpy( curwp->w_bufp->b_bname, "command");
  190.         /* make this window in VIEW mode, update all mode lines */
  191.         curwp->w_bufp->b_mode |= MDVIEW;
  192.         wp = wheadp;
  193.         while (wp != NULL) {
  194.                 wp->w_flag |= WFMODE;
  195.                 wp = wp->w_wndp;
  196.         }
  197.  
  198.         /* and get rid of the temporary file */
  199.         unlink(filnam);
  200.         return(TRUE);
  201. }
  202.  
  203.  
  204. /*
  205.  * filter a buffer through an external DOS program
  206.  * Bound to ^X #
  207.  * We use unique temporary file names so that multiple instances of
  208.  * MicroEMACS don't try to use the same file.
  209.  */
  210. PASCAL NEAR filter(f, n)
  211.  
  212. {
  213.         register int    s;      /* return status from CLI */
  214.         register BUFFER *bp;    /* pointer to buffer to zot */
  215.         char line[NLINE];       /* command line send to shell */
  216.         char tmpnam[NFILEN];    /* place to store real file name */
  217.         char *tmp;              /* ptr to TMP DOS environment variable */
  218.  
  219.         static char filnam1[NSTRING];
  220.         static char filnam2[NSTRING];
  221.  
  222.         /* don't allow this command if restricted */
  223.         if (restflag)
  224.                 return(resterr());
  225.  
  226.         if (curbp->b_mode&MDVIEW)       /* don't allow this command if  */
  227.                 return(rdonly());       /* we are in read only mode     */
  228.  
  229.         /* get the filter name and its args */
  230.         if ((s=mlreply("#", line, NLINE)) != TRUE)
  231.                 return(s);
  232.  
  233.         /* Call mktemp() to get unique filenames in the tmp directory. */
  234.         if ((tmp = getenv("TMP")) == NULL)
  235.                 filnam1[0] = filnam2[0] = 0;
  236.         else {
  237.                 strcpy(filnam1, tmp);
  238.                 strcpy(filnam2, tmp);
  239.                 if (filnam1[strlen(filnam1) - 1] != '\\') {
  240.                         strcat(filnam1, "\\");
  241.                         strcat(filnam2, "\\");
  242.                 }
  243.         }
  244.         strcat(filnam1,"eXXXXXX");
  245.         strcat(filnam2,"eXXXXXX");
  246.         mktemp(filnam1);
  247.  
  248.         /* setup the proper file names */
  249.         bp = curbp;
  250.         strcpy(tmpnam, bp->b_fname);    /* save the original name */
  251.         strcpy(bp->b_fname, filnam1);   /* set it to our new one */
  252.  
  253.         /* write it out, checking for errors */
  254.         if (writeout(filnam1, "w") != TRUE) {
  255.                 mlwrite(TEXT2);
  256. /*                      "[Cannot write filter file]" */
  257.                 strcpy(bp->b_fname, tmpnam);
  258.                 return(FALSE);
  259.         }
  260.  
  261.         mktemp(filnam2);
  262.         strcat(line, " <");             /* construct the command line */
  263.         strcat(line, filnam1);
  264.         strcat(line, " >");
  265.         strcat(line, filnam2);
  266.  
  267.         movecursor(term.t_nrow - 1, 0);
  268.         TTkclose();
  269.         system(line);
  270.         TTkopen();
  271.         sgarbf = TRUE;
  272.         s = TRUE;
  273.  
  274.         /* on failure, escape gracefully */
  275.         if (s != TRUE || (readin(filnam2,FALSE) == FALSE)) {
  276.                 mlwrite(TEXT3);
  277. /*                      "[Execution failed]" */
  278.                 strcpy(bp->b_fname, tmpnam);
  279.                 unlink(filnam1);
  280.                 unlink(filnam2);
  281.                 return(s);
  282.         }
  283.  
  284.         /* reset file name */
  285.         strcpy(bp->b_fname, tmpnam);    /* restore name */
  286.         bp->b_flag |= BFCHG;            /* flag it as changed */
  287.  
  288.         /* and get rid of the temporary file */
  289.         unlink(filnam1);
  290.         unlink(filnam2);
  291.         return(TRUE);
  292. }
  293.  
  294.  
  295.  
  296. /*      SHELL: Bring up a shell. */
  297.  
  298. shell(void)
  299. {
  300.         char *shell;            /* Name of system command processor */
  301.  
  302.  
  303.         /*  get name of system shell  */
  304.         if ((shell = getenv("COMSPEC")) == NULL) {
  305.                 return(FALSE);          /*  No shell located  */
  306.         }
  307.  
  308.         return (spawnlp(P_WAIT, shell, NULL));
  309. }
  310.  
  311.  
  312.  
  313. execprog( char *cmd)
  314. {
  315.         char             args[NSTRING];         /* args passed to program */
  316.         char            *sp;
  317.         char             failName[NFILEN];
  318.         char             prog[NSTRING];         /* name of program */
  319.         USHORT           i;
  320.  
  321.         /*
  322.          * Parse the command name from the command line and copy it
  323.          * into the prog and args arrays.
  324.          */
  325.         i = 0;
  326.         while (cmd[i]  &&  (cmd[i] != ' ')  &&  (cmd[i] != '\t')) {
  327.                 prog[i] = args[i] = cmd[i];
  328.                 i++;
  329.         }
  330.         prog[i] = args[i] = 0;          /* terminate with a null */
  331.  
  332.         /* skip whitespace and copy the args */
  333.         while (cmd[i]  &&  ((cmd[i] == ' ')  ||  (cmd[i] == '\t')))
  334.                 i++;
  335.         while (cmd[i]) {
  336.                 args[i] = cmd[i];
  337.                 i++;
  338.         }
  339.         args[i] = args[i + 1] = 0;      /* terminate with 2 nulls */
  340.  
  341.  
  342.         /* look up the program on the path, trying various extentions */
  343.         if ((sp = flook(prog, TRUE)) == NULL)
  344.                 if ((sp = flook(strcat(prog, ".exe"), TRUE)) == NULL) {
  345.                         return(FALSE);
  346.                 }
  347.         strcpy(prog, sp);
  348.  
  349.         /*
  350.          * Execute the program synchronously.  We wait for child
  351.          * to return.
  352.          */
  353.         return (0 == spawnl(P_WAIT, prog, args, NULL));
  354. }
  355.  
  356.  
  357. /*      FILE Directory routines         */
  358.  
  359. struct _finddata_t pBuf; /* buffer to hold file information */
  360. long lDir;              /* directory handle */
  361. int num_found;          /* number of directory entries found/to find */
  362.  
  363. char path[NFILEN];      /* path of file to find */
  364. char rbuf[NFILEN];      /* return file buffer */
  365.  
  366. /*      do a wild card directory search (for file name completion) */
  367.  
  368. char *PASCAL NEAR getffile(fspec)
  369.  
  370. char *fspec;    /* pattern to match */
  371.  
  372. {
  373.         register int index;             /* index into various strings */
  374.         register int point;             /* index into other strings */
  375.         register int extflag;           /* does the file have an extention? */
  376.         char fname[NFILEN];             /* file/path for DOS call */
  377.  
  378.         /* first parse the file path off the file spec */
  379.         strcpy(path, fspec);
  380.         index = strlen(path) - 1;
  381.         while (index >= 0 && (path[index] != '/' &&
  382.                                 path[index] != '\\' && path[index] != ':'))
  383.                 --index;
  384.         path[index+1] = 0;
  385.  
  386.         /* check for an extension */
  387.         point = strlen(fspec) - 1;
  388.         extflag = FALSE;
  389.         while (point > index) {
  390.                 if (fspec[point] == '.') {
  391.                         extflag = TRUE;
  392.                         break;
  393.                 }
  394.                 point--;
  395.         }
  396.  
  397.         /* construct the composite wild card spec */
  398.         strcpy(fname, path);
  399.         strcat(fname, &fspec[index+1]);
  400.         strcat(fname, "*");
  401.         if (extflag == FALSE)
  402.                 strcat(fname, ".*");
  403.  
  404.         /* and call for the first file */
  405.         num_found = 1;
  406.         if ((lDir = _findfirst(fname, &pBuf)) == NULL)
  407.                 return(NULL);
  408.  
  409.         /* return the first file name! */
  410.         strcpy(rbuf, path);
  411.         strcat(rbuf, pBuf.name);
  412.         mklower(rbuf);
  413.         if (pBuf.attrib == _A_SUBDIR)
  414.                 strcat(rbuf, DIRSEPSTR);
  415.         return(rbuf);
  416. }
  417.  
  418. char *PASCAL NEAR getnfile()
  419.  
  420. {
  421.         register int index;             /* index into various strings */
  422.         register int point;             /* index into other strings */
  423.         register int extflag;           /* does the file have an extention? */
  424.         char fname[NFILEN];             /* file/path for DOS call */
  425.  
  426.         /* and call for the next file */
  427.         if (_findnext(lDir, &pBuf) != 0)
  428.                 return(NULL);
  429.  
  430.         /* return the first file name! */
  431.         strcpy(rbuf, path);
  432.         strcat(rbuf, pBuf.name);
  433.         mklower(rbuf);
  434.         if (pBuf.attrib == _A_SUBDIR)
  435.                 strcat(rbuf, DIRSEPSTR);
  436.         return(rbuf);
  437. }
  438.  
  439. /* return a system dependant string with the current time */
  440.  
  441. char *PASCAL NEAR timeset()
  442.  
  443. {
  444.         register char *sp;      /* temp string pointer */
  445.         char buf[16];           /* time data buffer */
  446.         extern char *ctime();
  447.  
  448.         time(buf);
  449.         sp = ctime(buf);
  450.         sp[strlen(sp)-1] = 0;
  451.         return(sp);
  452. }
  453.  
  454. #if     OBSOLETE
  455. /*      extcode:        resolve MSDOS extended character codes
  456.                         encoding the proper sequences into emacs
  457.                         printable character specifications
  458. */
  459.  
  460. int extcode(
  461.         unsigned c      /* byte following a zero extended char byte */
  462. )
  463.  
  464. {
  465.         /* function keys 1 through 9 */
  466.         if (c >= 59 && c < 68)
  467.                 return(SPEC | c - 58 + '0');
  468.  
  469.         /* function key 10 */
  470.         if (c == 68)
  471.                 return(SPEC | '0');
  472.  
  473.         /* shifted function keys */
  474.         if (c >= 84 && c < 93)
  475.                 return(SPEC | SHFT | c - 83 + '0');
  476.         if (c == 93)
  477.                 return(SPEC | SHFT | '0');
  478.  
  479.         /* control function keys */
  480.         if (c >= 94 && c < 103)
  481.                 return(SPEC | CTRL | c - 93 + '0');
  482.         if (c == 103)
  483.                 return(SPEC | CTRL | '0');
  484.  
  485.         /* ALTed function keys */
  486.         if (c >= 104 && c < 113)
  487.                 return(SPEC | ALTD | c - 103 + '0');
  488.         if (c == 113)
  489.                 return(SPEC | ALTD | '0');
  490.  
  491.         /* ALTed number keys */
  492.         if (c >= 120 && c < 129)
  493.                 return(ALTD | c - 119 + '0');
  494.         if (c == 130)
  495.                 return(ALTD | '0');
  496.  
  497.         /* some others as well */
  498.         switch (c) {
  499.                 case 3:         return(0);              /* null */
  500.                 case 15:        return(SHFT | CTRL | 'I');      /* backtab */
  501.  
  502.                 case 16:        return(ALTD | 'Q');
  503.                 case 17:        return(ALTD | 'W');
  504.                 case 18:        return(ALTD | 'E');
  505.                 case 19:        return(ALTD | 'R');
  506.                 case 20:        return(ALTD | 'T');
  507.                 case 21:        return(ALTD | 'Y');
  508.                 case 22:        return(ALTD | 'U');
  509.                 case 23:        return(ALTD | 'I');
  510.                 case 24:        return(ALTD | 'O');
  511.                 case 25:        return(ALTD | 'P');
  512.  
  513.                 case 30:        return(ALTD | 'A');
  514.                 case 31:        return(ALTD | 'S');
  515.                 case 32:        return(ALTD | 'D');
  516.                 case 33:        return(ALTD | 'F');
  517.                 case 34:        return(ALTD | 'G');
  518.                 case 35:        return(ALTD | 'H');
  519.                 case 36:        return(ALTD | 'J');
  520.                 case 37:        return(ALTD | 'K');
  521.                 case 38:        return(ALTD | 'L');
  522.  
  523.                 case 44:        return(ALTD | 'Z');
  524.                 case 45:        return(ALTD | 'X');
  525.                 case 46:        return(ALTD | 'C');
  526.                 case 47:        return(ALTD | 'V');
  527.                 case 48:        return(ALTD | 'B');
  528.                 case 49:        return(ALTD | 'N');
  529.                 case 50:        return(ALTD | 'M');
  530.  
  531.                 case 71:        return(SPEC | '<');     /* HOME */
  532.                 case 72:        return(SPEC | 'P');     /* cursor up */
  533.                 case 73:        return(SPEC | 'Z');     /* page up */
  534.                 case 75:        return(SPEC | 'B');     /* cursor left */
  535.                 case 77:        return(SPEC | 'F');     /* cursor right */
  536.                 case 79:        return(SPEC | '>');     /* end */
  537.                 case 80:        return(SPEC | 'N');     /* cursor down */
  538.                 case 81:        return(SPEC | 'V');     /* page down */
  539.                 case 82:        return(SPEC | 'C');     /* insert */
  540.                 case 83:        return(SPEC | 'D');     /* delete */
  541.                 case 115:       return(SPEC | CTRL | 'B');      /* control left */
  542.                 case 116:       return(SPEC | CTRL | 'F');      /* control right */
  543.                 case 117:       return(SPEC | CTRL | '>');      /* control END */
  544.                 case 118:       return(SPEC | CTRL | 'V');      /* control page down */
  545.                 case 119:       return(SPEC | CTRL | '<');      /* control HOME */
  546.                 case 132:       return(SPEC | CTRL | 'Z');      /* control page up */
  547.         }
  548.  
  549.         return(ALTD | c);
  550. }
  551. #endif  /* obsolete */
  552. #endif
  553.  
  554. #undef va_start
  555. #undef va_end
  556. #include <varargs.h>
  557. int dprintf(va_alist, ...)
  558. va_dcl
  559. {
  560.     va_list arg_ptr;
  561.     char buffer[200];
  562.     char *fmt;
  563.  
  564.     va_start(arg_ptr);
  565.     fmt = va_arg(arg_ptr, char *);
  566.  
  567.     vsprintf(buffer, fmt, arg_ptr);
  568.     SetConsoleTitle(buffer);
  569. }
  570.  
  571.